// Copyright (C) Calum Grant 2008

namespace dynamic
{
	inline internal::var_member<const char*> var::operator[](const char * m) const
	{ 
		return internal::var_member<const char*>(*this, m); 
	}

	template<typename T>
	var::var(const internal::var_member<T> & m) : m_variant(m.get_var().m_variant)
	{ 
	}

	namespace internal
	{
		template<typename Derived, typename DerefType> template<typename T>
		var internal::var_methods<Derived,DerefType>::operator+(const T & t) const
		{
			return deref().impl().op_add(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		internal::extender internal::var_methods<Derived,DerefType>::extend(const char * m, const T t)
		{
			deref()[m]=t;
			return internal::extender(deref());
		}

		template<typename Derived, typename DerefType> template<typename T>
		var internal::var_methods<Derived,DerefType>::operator-(const T & t) const
		{
			return deref().impl().op_sub(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		var var_methods<Derived,DerefType>::operator*(const T & t) const
		{
			return deref().impl().op_mul(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		var var_methods<Derived,DerefType>::operator/(const T & t) const
		{
			return deref().impl().op_div(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		var var_methods<Derived,DerefType>::operator%(const T & t) const
		{
			return deref().impl().op_mod(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		var var_methods<Derived,DerefType>::operator<<(const T & t) const
		{
			return deref().impl().op_lshift(t);
		}

		template<typename Derived, typename DerefType> template<typename T>
		var var_methods<Derived,DerefType>::operator>>(const T & t) const
		{
			return deref().impl().op_rshift(t);
		}

		inline var operator+(const char * t, const var & v)
		{
			return var(t) + v;
		}

		template<typename T>
		inline var operator+(const char * t, const internal::var_member<T> & v)
		{
			return var(t) + v;
		}

		template<typename T>
		internal::var_member<const char*> internal::var_member_base<T>::operator[](const char * m) const
		{ 
			return internal::var_member<const char*>(get_var(), m);
		}

		template<typename T> template<typename U>
		internal::var_member<var> internal::var_member_base<T>::operator[]
			(const internal::var_member_base<U> & m) const
		{ 
			return internal::var_member<var>(get_var(), m.get_var());	
		}

		template<typename T>
		internal::var_member<int> internal::var_member_base<T>::operator[](int m) const
		{ 
			return internal::var_member<int>(get_var(), m);
		}

		template<typename T>
		internal::var_member<var> internal::var_member_base<T>::operator[](const var & m) const
		{ 
			return internal::var_member<var>(get_var(), m);
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()() const
		{ return deref().impl().call(); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0) const
		{ return deref().impl().call(a0); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1) const
		{ return deref().impl().call(a0, a1); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2) const
		{ return deref().impl().call(a0, a1, a2); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3) const
		{ return deref().impl().call(a0, a1, a2, a3); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4) const
		{ return deref().impl().call(a0, a1, a2, a3, a4); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4, const var & a5) const
		{ return deref().impl().call(a0, a1, a2, a3, a4, a5); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4, const var & a5, const var & a6) const
		{ return deref().impl().call(a0, a1, a2, a3, a4, a5, a6); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4, const var & a5, const var & a6, const var & a7) const
		{ return deref().impl().call(a0, a1, a2, a3, a4, a5, a6, a7); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4, const var & a5, const var & a6, const var & a7, const var & a8) const
		{ return deref().impl().call(a0, a1, a2, a3, a4, a5, a6, a7, a8); }

		template<typename Derived, typename DerefType> 
		var var_methods<Derived,DerefType>::operator()(const var & a0, const var & a1, const var & a2, const var & a3, const var & a4, const var & a5, const var & a6, const var & a7, const var & a8, const var & a9) const
		{ return deref().impl().call(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }

		template<typename Derived, typename DerefType> 
		std::string var_methods<Derived, DerefType>::class_name() const
		{ 
			return deref().impl().class_name(); 
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived, DerefType>::keys() const
		{ 
			return deref().impl().keys(); 
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived, DerefType>::values() const
		{ 
			return deref().impl().values(); 
		}

		template<typename Derived, typename DerefType> 
		int var_methods<Derived, DerefType>::max_args() const
		{ 
			return deref().impl().max_args(); 
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived, DerefType>::proxy() const
		{ 
			return deref().impl().proxy(); 
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived, DerefType>::enumerator() const
		{ 
			return deref().impl().enumerator(); 
		}

		template<typename Derived, typename DerefType> 
		var var_methods<Derived, DerefType>::reverse_enumerator() const
		{ 
			return deref().impl().reverse_enumerator(); 
		}

		template<typename Derived,typename Deref>
		var var_methods<Derived,Deref>::clone() const 
		{ 
			return deref().impl().clone(); 
		}

		template<typename Derived,typename Deref>
		var var_methods<Derived,Deref>::begin() const 
		{ 
			return deref().impl().begin(); 
		}

		template<typename Derived,typename Deref>
		var var_methods<Derived,Deref>::end() const 
		{ 
			return deref().impl().end(); 
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::rbegin() const 
		{ 
			return deref().impl().rbegin(); 
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::rend() const 
		{ 
			return deref().impl().rend(); 
		}

		template<typename Derived, typename Deref>
		int var_methods<Derived,Deref>::size() const 
		{ 
			return deref().impl().size(); 
		}

		template<typename Derived, typename Deref>
		void var_methods<Derived,Deref>::resize(const var & new_size) 
		{ 
			return deref().impl().resize(new_size.as_int()); 
		}

		template<typename Derived, typename Deref>
		bool var_methods<Derived,Deref>::empty() const 
		{ 
			return deref().impl().empty(); 
		}

		template<typename Derived, typename Deref>
		void var_methods<Derived,Deref>::clear()
		{
			deref().impl().clear();
		}

		template<typename Derived, typename Deref>
		void var_methods<Derived,Deref>::push_back(const var & t)
		{
			deref().impl().push_back(t);
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::pop_back()
		{
			return deref().impl().pop_back();
		}

		template<typename Derived, typename Deref> 
		void var_methods<Derived,Deref>::push_front(const var & t)
		{
			deref().impl().push_front(t);
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::pop_front()
		{
			return deref().impl().pop_front();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::front() const
		{
			return deref().impl().front();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::back() const
		{
			return deref().impl().back();
		}

		template<typename Derived, typename Deref>
		void var_methods<Derived,Deref>::insert(const var & t)
		{
			deref().impl().insert(t);
		}

		template<typename Derived, typename Deref>
		void var_methods<Derived,Deref>::insert(const var & t, const var & u)
		{
			deref().impl().insert(t,u);
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::key() const
		{
			return deref().impl().key();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::value() const
		{
			return deref().impl().value();
		}

		template<typename Derived, typename Deref> 
		bool var_methods<Derived,Deref>::contains(const var & t) const
		{
			return deref().impl().contains(t);
		}

		template<typename Derived, typename Deref> 
		void var_methods<Derived,Deref>::erase(const var & t)
		{
			deref().impl().erase(t);
		}

		template<typename Derived, typename Deref> 
		void var_methods<Derived,Deref>::mixin(const var & t)
		{
			deref().impl().mixin(t);
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator++(int)
		{
			var tmp = deref().impl().clone();
			deref().impl().op_inc();
			return tmp;
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator--(int)
		{
			var tmp = deref().impl().clone();
			deref().impl().op_dec();
			return tmp;
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator*()const
		{
			return deref().impl().deref();
		}

		template<typename Derived, typename Deref>
		internal::var_deref var_methods<Derived,Deref>::operator->() const
		{
			return deref().impl().deref();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator+() const
		{
			return deref().impl().op_pos();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator~() const
		{
			return deref().impl().op_inv();
		}

		template<typename Derived, typename Deref>
		var var_methods<Derived,Deref>::operator-() const
		{
			return deref().impl().op_neg();
		}

		template<typename Derived,typename Deref>
		string var_methods<Derived,Deref>::as_string() const
		{
			return to_string(deref());
		}

		template<typename Derived,typename Deref>
		wstring var_methods<Derived,Deref>::as_wstring() const
		{
			return to_wstring(deref());
		}
	}
}
